from typing import Optional, List, Dict, Any, Union
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete, func, and_, or_

from module_kylin.entity.future_trade_cal import KylinFutureTradeCal
from module_kylin.entity.vo.future_trade_cal_vo import (
    FutureTradeCalPageQueryModel,
    FutureTradeCalQueryModel
)


class FutureTradeCalDao:
    """
    期货交易日历数据访问层
    """

    @classmethod
    async def get_trade_cal_by_date(cls, db: AsyncSession, cal_date: str) -> Optional[KylinFutureTradeCal]:
        """
        根据日期获取交易日历信息
        
        Args:
            db: 数据库会话
            cal_date: 日历日期
            
        Returns:
            KylinFutureTradeCal对象或None
        """
        stmt = select(KylinFutureTradeCal).where(KylinFutureTradeCal.cal_date == cal_date)
        result = await db.execute(stmt)
        return result.scalar_one_or_none()
    
    @classmethod
    async def get_max_cal_date(cls, db: AsyncSession) -> Optional[str]:
        """
        获取最大的日历日期
        
        Args:
            db: 数据库会话
            
        Returns:
            最大日期字符串或None
        """
        stmt = select(func.max(KylinFutureTradeCal.cal_date))
        result = await db.execute(stmt)
        return result.scalar()
    
    @classmethod
    async def get_trade_cal_list(
        cls, 
        db: AsyncSession, 
        query_model: Union[FutureTradeCalPageQueryModel, FutureTradeCalQueryModel]
    ) -> List[KylinFutureTradeCal]:
        """
        获取交易日历列表
        
        Args:
            db: 数据库会话
            query_model: 查询模型
            
        Returns:
            交易日历列表
        """
        stmt = select(KylinFutureTradeCal)
        
        # 日期范围查询
        if hasattr(query_model, 'begin_date') and query_model.begin_date:
            stmt = stmt.where(KylinFutureTradeCal.cal_date >= query_model.begin_date)
        if hasattr(query_model, 'end_date') and query_model.end_date:
            stmt = stmt.where(KylinFutureTradeCal.cal_date <= query_model.end_date)
        
        # 交易状态查询
        if hasattr(query_model, 'is_open') and query_model.is_open is not None:
            stmt = stmt.where(KylinFutureTradeCal.is_open == query_model.is_open)
        
        # 按日期倒序排序
        stmt = stmt.order_by(KylinFutureTradeCal.cal_date.desc())
        
        result = await db.execute(stmt)
        return result.scalars().all()
    
    @classmethod
    async def add_trade_cal(cls, db: AsyncSession, trade_cal: KylinFutureTradeCal) -> None:
        """
        添加交易日历
        
        Args:
            db: 数据库会话
            trade_cal: 交易日历对象
        """
        db.add(trade_cal)
    
    @classmethod
    async def batch_add_trade_cal(cls, db: AsyncSession, trade_cal_list: List[KylinFutureTradeCal]) -> None:
        """
        批量添加交易日历
        
        Args:
            db: 数据库会话
            trade_cal_list: 交易日历对象列表
        """
        db.add_all(trade_cal_list)
    
    @classmethod
    async def update_trade_cal(
        cls, 
        db: AsyncSession, 
        cal_id: int, 
        update_data: Dict[str, Any]
    ) -> int:
        """
        更新交易日历
        
        Args:
            db: 数据库会话
            cal_id: 日历ID
            update_data: 更新数据
            
        Returns:
            更新的行数
        """
        stmt = update(KylinFutureTradeCal).where(KylinFutureTradeCal.id == cal_id).values(**update_data)
        result = await db.execute(stmt)
        return result.rowcount
    
    @classmethod
    async def delete_trade_cal(cls, db: AsyncSession, cal_ids: List[int]) -> int:
        """
        删除交易日历
        
        Args:
            db: 数据库会话
            cal_ids: 日历ID列表
            
        Returns:
            删除的行数
        """
        stmt = delete(KylinFutureTradeCal).where(KylinFutureTradeCal.id.in_(cal_ids))
        result = await db.execute(stmt)
        return result.rowcount